
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from LogisticsCard.models import CardOrder, PaymentRecord
from django.utils import timezone
from xml.etree import ElementTree as ET
from LogisticsCard.utils.wechatpay import WXPay

def xml_to_dict(xml_data):
    if isinstance(xml_data, bytes):
        xml_data = xml_data.decode('utf-8', errors='replace')
    result = {}
    root = ET.fromstring(xml_data)
    for child in root:
        result[child.tag] = child.text
    return result

def dict_to_xml(data):
    xml = ['<xml>']
    for k, v in data.items():
        xml.append(f'<{k}><![CDATA[{v}]]></{k}>')
    xml.append('</xml>')
    return ''.join(xml)

@csrf_exempt
def wechatpay_notify(request):
    # 微信支付回调，POST，内容为XML
    try:
        data = xml_to_dict(request.body)
        # 通信标识
        if data.get('return_code') != 'SUCCESS':
            return HttpResponse(dict_to_xml({'return_code': 'FAIL', 'return_msg': '通信失败'}), content_type='text/xml')
        # 签名校验
        wxpay = WXPay()
        sign = data.get('sign')
        sign_type = data.get('sign_type', 'MD5')
        check_sign = wxpay.create_sign({k: v for k, v in data.items() if k != 'sign'})
        if sign != check_sign:
            return HttpResponse(dict_to_xml({'return_code': 'FAIL', 'return_msg': '签名失败'}), content_type='text/xml')
        # 业务结果
        if data.get('result_code') != 'SUCCESS':
            return HttpResponse(dict_to_xml({'return_code': 'FAIL', 'return_msg': '业务失败'}), content_type='text/xml')
        out_trade_no = data.get('out_trade_no')
        wx_trade_no = data.get('transaction_id')
        pay_time = data.get('time_end')
        total_fee = int(data.get('total_fee', 0))
        order = CardOrder.objects.filter(order_no=out_trade_no).first()
        if not order:
            return HttpResponse(dict_to_xml({'return_code': 'FAIL', 'return_msg': '订单不存在'}), content_type='text/xml')
        # 金额校验
        if int(order.amount * 100) != total_fee:
            return HttpResponse(dict_to_xml({'return_code': 'FAIL', 'return_msg': '金额不符'}), content_type='text/xml')
        # 幂等处理
        if order.status == 'paid':
            return HttpResponse(dict_to_xml({'return_code': 'SUCCESS', 'return_msg': 'OK'}), content_type='text/xml')
        order.status = 'paid'
        order.save()
        PaymentRecord.objects.update_or_create(
            order=order,
            wx_trade_no=wx_trade_no,
            defaults={
                'out_trade_no': out_trade_no,
                'pay_time': timezone.now(),
                'is_paid': True,
                'raw_notify': request.body.decode('utf-8', errors='replace')
            }
        )
        return HttpResponse(dict_to_xml({'return_code': 'SUCCESS', 'return_msg': 'OK'}), content_type='text/xml')
    except Exception as e:
        return HttpResponse(dict_to_xml({'return_code': 'FAIL', 'return_msg': str(e)}), content_type='text/xml')
